use std::any::Any;

pub fn learn_struct() {
  //_learn_struct0();
  //_learn_enum0();
  //_learn_opt0();
  _learn_opt1();
}

#[derive(Debug)]
struct Foo;

#[derive(Debug)]
struct Point {
  x: u8,
  y: u32,
}

impl Point {
  fn dis(&self) -> u32 {
    (self.x as u32) + self.y
  }
}
impl Drop for Point {
  fn drop(&mut self) {
    println!("drop point: {}", self.x);
  }
}

fn _learn_struct0() {
  let f = Foo;
  println!("f1:{:?}", f.type_id());
  let p = &Point { x: 10, y: 22 };
  println!("p.dis:{}", p.dis());

  let a = &mut 8;
  *a = 7;
  println!("{}", a);
  let b = &8;
  // *b = 7; // cannot to write

  let p2 = &mut Point { x: 5, y: 1 };
  p2.x = 3;
  println!("p2.dis:{}", p2.dis());
}

#[derive(Debug)]
enum StateEnum {
  NORMAL,
  STOP,
}

fn _learn_enum0() {
  let a = StateEnum::NORMAL;
  let b = StateEnum::STOP;
  match a {
    StateEnum::NORMAL => println!(":normal"),
    StateEnum::STOP => println!(":stop"),
  }
}

fn _learn_opt0() {
  let a = Some(5);
  let b = Some('a');
  let c = Some(String::from("hello"));
  let d1: Option<String> = None;
  let d2: Option<String> = None;
  let d3: Option<String> = None;
  let d4: Option<usize> = None;
  let d5: Option<char> = None;
  let d6: Option<bool> = None;
  let d7: Option<f32> = None;
  let d8: Option<f64> = None;
  let d9: Option<u8> = None;
  let d10: Option<()> = None;

  let e = d1.unwrap_or_else(|| String::from("a"));
  let f = d2.unwrap_or_default();
  let g = d3.unwrap_or(String::from("world"));
  println!("e:[{}]", e);
  println!("f:[{}]", f);
  println!("g:[{}]", g);

  println!("usize default:[{}]", d4.unwrap_or_default());
  println!("char default:[{}]", d5.unwrap_or_default());
  println!("bool default:[{}]", d6.unwrap_or_default());
  println!("f32 default:[{}]", d7.unwrap_or_default());
  println!("f64 default:[{}]", d8.unwrap_or_default());
  println!("u8 default:[{}]", d9.unwrap_or_default());
  //println!("() default:[{}]", d10.unwrap());
}

fn _learn_opt1() {
  fn plus_one(x: Option<i32>) -> Option<i32> {
    match x {
      None => None,
      Some(i) => Some(i + 1),
    }
  }
  let five = Some(5);
  let six = plus_one(five);
  let none = plus_one(None);
  println!("{}, {:?}", six.unwrap(), none);

  let config_max = Some(3u8);
  // 只匹配一个模式,其他模式忽略,这样写有点繁琐
  match config_max {
    Some(max) => println!("match:{}", max),
    _ => (),
  }
  // 使用if let来简化,但也会失去match强制要求的穷尽性检查
  if let Some(max) = config_max {
    println!("if let:{}", max);
  }
  // 添加else来补充穷尽性检查
  // else{}
}
